# tools.postcss

- **Type:** `Object | Function`
- **Default:**

```js
const defaultOptions = {
  postcssOptions: {
    config: false,
    sourceMap: rsbuildConfig.output.sourceMap.css,
  },
};
```

Rsbuild integrates PostCSS by default. You can configure [postcss-loader](https://github.com/webpack/postcss-loader) through `tools.postcss`.

## Function type

When `tools.postcss` is a function, the default options will be passed in as the first parameter. You can directly modify this object or return a new object as the final options. For example:

For example, to add a PostCSS plugin, you can call the [addPlugins](#addplugins) utility function:

```ts title="rsbuild.config.ts"
export default {
  tools: {
    postcss: (opts, { addPlugins }) => {
      addPlugins(require('postcss-px-to-viewport'));
    },
  },
};
```

To pass parameters to the PostCSS plugin, call the PostCSS plugin as a function:

```ts title="rsbuild.config.ts"
export default {
  tools: {
    postcss: (opts, { addPlugins }) => {
      const viewportPlugin = require('postcss-px-to-viewport')({
        viewportWidth: 375,
      });
      addPlugins(viewportPlugin);
    },
  },
};
```

You can also modify the default `postcss-loader` options:

```ts title="rsbuild.config.ts"
export default {
  tools: {
    postcss: (opts) => {
      opts.sourceMap = false;
    },
  },
};
```

`tools.postcss` can return a config object and completely replace the default config:

```ts title="rsbuild.config.ts"
export default {
  tools: {
    postcss: () => {
      return {
        postcssOptions: {
          plugins: [require('postcss-px-to-viewport')],
        },
      };
    },
  },
};
```

## Object type

When `tools.postcss` is an object, it will be merged with the default configuration using `Object.assign`. Note that `Object.assign` is a shallow copy and will completely overwrite the built-in `presets` or `plugins` array, please use it with caution.

```ts title="rsbuild.config.ts"
export default {
  tools: {
    postcss: {
      // As `Object.assign` is used, the default postcssOptions will be overwritten.
      postcssOptions: {
        plugins: [require('postcss-px-to-viewport')],
      },
    },
  },
};
```

## Utils

### addPlugins

- **Type:**

```ts
type AddPlugins = (
  plugins: PostCSSPlugin | PostCSSPlugin[],
  options?: {
    /**
     * Controls where the plugin is placed relative to the existing PostCSS plugins.
     * @default 'post'
     */
    order?: 'pre' | 'post';
  },
) => void;
```

For adding additional PostCSS plugins, You can pass in a single PostCSS plugin, or an array of PostCSS plugins.

```ts title="rsbuild.config.ts"
export default {
  tools: {
    postcss: (config, { addPlugins }) => {
      // Add a PostCSS Plugin
      addPlugins(require('postcss-preset-env'));
      // Add multiple PostCSS Plugins
      addPlugins([require('postcss-preset-env'), require('postcss-import')]);
    },
  },
};
```

To add plugins before the existing plugins, set `order` option to `pre`:

```ts title="rsbuild.config.ts"
export default {
  tools: {
    postcss: (config, { addPlugins }) => {
      addPlugins(require('postcss-preset-env'), { order: 'pre' });
    },
  },
};
```

## Practice

### Multiple PostCSS options

`tools.postcss.postcssOptions` can be set to a function, which receives the Rspack's `loaderContext` as a parameter. This allows you to use different PostCSS options for different file paths.

For example, use `postcss-plugin-a` for file paths containing `foo`, and use `postcss-plugin-b` for other file paths:

```ts title="rsbuild.config.ts"
export default {
  tools: {
    postcss: {
      postcssOptions: (loaderContext) => {
        if (/foo/.test(loaderContext.resourcePath)) {
          return {
            plugins: [require('postcss-plugin-a')],
          };
        }
        return {
          plugins: [require('postcss-plugin-b')],
        };
      },
    },
  },
};
```

:::tip
If the project contains a `postcss.config.*` config file, its content will be merged with `tools.postcss.postcssOptions`, and the latter's priority is higher. The `plugins` array will be merged into a single array.
:::

## Notes

### PostCSS version

Rsbuild uses the PostCSS v8. When you use third-party PostCSS plugins, please pay attention to whether the PostCSS version is compatible. Some legacy plugins may not work in PostCSS v8.

### PostCSS config loading

Rsbuild uses [postcss-load-config](https://github.com/postcss/postcss-load-config) to load PostCSS config files and merge them with the default config.

Rsbuild internally sets the `postcss-loader`'s `postcssOptions.config` option to `false` to avoid loading config files repeatedly.

## Version history

| Version | Changes                                         |
| ------- | ----------------------------------------------- |
| v1.6.8  | Added `order` option to the `addPlugins` method |
